/*
 * i2c.c
 *
 *  Created on: Apr 5, 2016
 *
 */

#include "LPC8xx.h"
#include "utilities.h"
#include "i2c.h"
#include "stdint.h"
 #define SCL_PIN       P0_10         // P0_10 for I2C0
  #define SCL_IOCON_REG PIO0_10
  #define SDA_PIN       P0_11         // P0_11 for I2C0
  #define SDA_IOCON_REG PIO0_11
typedef enum {FALSE = 0, TRUE = !FALSE} Bool;
unsigned char AD7416_SystemError;
unsigned int Temperature; //温度
unsigned char ZorF; //正还是负
//自加的
static __inline _Bool Chip(uint32_t pin)
{
  // LPC_GPIO_PORT->DIR0 &= ~((1<<SDA_PIN)|(1<<SCL_PIN)); // Input GPIOs to input mode 输入模式
	return (_Bool) LPC_GPIO_PORT->B0[pin];
}
void I2C_GPIO_Config(void)
{


	  LPC_SYSCON->SYSAHBCLKCTRL[0] |= (1<<18|1<<6);//使能SWM和IOCON和GPIO0时钟GPIO1                      加了1<<20
	 LPC_SWM->PINENABLE0 |= (1<<13|1<<12);

	//  LPC_SYSCON->SYSAHBCLKCTRL[0] &= ~1<<7;//不使能SWM时钟  节能

	// GPIOInit();  //GPIO初始化  有问题
	 LPC_SYSCON->PRESETCTRL[0] &= (~(1<<6) & ~(1<<20));
	   LPC_SYSCON->PRESETCTRL[0] |= ~(~(1<<6) & ~(1<<20));

	  LPC_IOCON->SCL_IOCON_REG |= 1<<10; //使P1_14为开漏
	  LPC_IOCON->SDA_IOCON_REG |= 1<<10;//使P1_15为开漏
	  SCL_H;
	  SDA_H;
	  LPC_GPIO_PORT->SET0  = (1<<SCL_PIN)|(1<<SDA_PIN);
	  LPC_GPIO_PORT->DIR0 |= (1<<SCL_PIN)|(1<<SDA_PIN);  // 输出模式

}
void delay_us(int time_us )
{
 int i,j;
 for( i=0;i<time_us;i++ )
 {
		for( j=0;j<11;j++ );//1us
 }
}
void delay_ms(int time_ms)
{
	int i;
 for( i=0;i<time_ms;i++ )
 {
		delay_us(11000);
 }

}
void DELAY(int z)//延时zms
{
int x,y;
for(x = z;x > 0;x--)
for(y = 110;y > 0;y--);
}
void I2C_delay(void)
{
   uint8_t i=100; //50
   while(i)
   {
     i--;
   }
}

uint8_t I2C_Start(void)
{
	SDA_H;
	SCL_H;
	I2C_delay();
	if(!Chip(11))
    return FALSE;	//SDAÏßÎªµÍµçÆ½Ôò×ÜÏßÃ¦,ÍË³ö
	SDA_L;
	I2C_delay();
	if(Chip(11))
    return FALSE;	//SDAÏßÎª¸ßµçÆ½Ôò×ÜÏß³ö´í,ÍË³ö
	SDA_L;
	I2C_delay();
	return TRUE;
}

void I2C_Stop(void)
{
	SCL_L;
	I2C_delay();
	SDA_L;
	I2C_delay();
	SCL_H;
	I2C_delay();
	SDA_H;
	I2C_delay();
}

void I2C_Ack(void)
{
	SCL_L;
	I2C_delay();
	SDA_L;
	I2C_delay();
	SCL_H;
	I2C_delay();
	SCL_L;
	I2C_delay();
}

void I2C_NoAck(void)
{
	SCL_L;
	I2C_delay();
	SDA_H;
	I2C_delay();
	SCL_H;
	I2C_delay();
	SCL_L;
	I2C_delay();
}

uint8_t I2C_WaitAck(void) 	 //·µ»ØÎª:=1ÓÐACK,=0ÎÞACK
{
	SCL_L;
	I2C_delay();
	SDA_H;
	I2C_delay();
	SCL_H;
	I2C_delay();
	if(Chip(11))
	{
      SCL_L;
      return FALSE;
	}
	SCL_L;
	return TRUE;
}

/* ´ó¶àÊýAT24CÏµÁÐÖ§³Ö memory reset */
void EEP_MemoryReset(void)
{
	uint8_t i=9;
	SDA_H;
	SCL_H;
	I2C_delay();
	I2C_delay();

	while(i--)
	{
		SCL_L;
		I2C_delay();
		I2C_delay();

		SCL_H;
		I2C_delay();
		I2C_delay();
	}
	I2C_Start();
}

/* ²¿·ÖAT24CÏµÁÐÖ§³Ö software reset */
void EEP_SoftReset(void)
{
	uint8_t i=9;
	SDA_H;
	SCL_H;
	I2C_Start();

	while(i--)
	{
		SCL_L;
		I2C_delay();
		I2C_delay();

		SCL_H;
		I2C_delay();
		I2C_delay();
	}
	I2C_Start();
	I2C_Stop();
}

void I2C_SendByte(uint8_t SendByte) //Êý¾Ý´Ó¸ßÎ»µ½µÍÎ»//
{
    uint8_t i=8;
    while(i--)
    {
      SCL_L;
      I2C_delay();
      if(SendByte&0x80)
        SDA_H;
      else
        SDA_L;
      SendByte<<=1;
      I2C_delay();

      SCL_H;
      I2C_delay();

    }
    SCL_L;
}

uint8_t I2C_ReceiveByte(void)  //Êý¾Ý´Ó¸ßÎ»µ½µÍÎ»//
{
    uint8_t i=8;
    uint8_t ReceiveByte=0;

    SDA_H;
    while(i--)
    {
      ReceiveByte<<=1;
      SCL_L;
      I2C_delay();
    //  I2C_delay();

      SCL_H;
      I2C_delay();
      if(Chip(11))
      {
        ReceiveByte|=0x01;
      }
   //   I2C_delay();
    }
    SCL_L;
    return ReceiveByte;
}

//Ð´Èë1×Ö½ÚÊý¾Ý       ´ýÐ´ÈëÊý¾Ý    ´ýÐ´ÈëµØÖ·       Æ÷¼þÀàÐÍ(24c16»òSD2403)
uint8_t I2C_WriteByte(uint8_t SendByte, uint16_t WriteAddress, uint8_t DeviceAddress)
{
    if(!I2C_Start())
      return FALSE;
    I2C_SendByte(((WriteAddress & 0x0700) >>7) | DeviceAddress & 0xFFFE);//ÉèÖÃ¸ßÆðÊ¼µØÖ·+Æ÷¼þµØÖ·
    if(!I2C_WaitAck())
    {
      I2C_Stop();
      return FALSE;
    }

    I2C_SendByte((uint8_t)(WriteAddress & 0x00FF));   //ÉèÖÃµÍÆðÊ¼µØÖ·
    I2C_WaitAck();

    I2C_SendByte(SendByte);
    I2C_WaitAck();

    I2C_Stop();
	//×¢Òâ£ºÒòÎªÕâÀïÒªµÈ´ýEEPROMÐ´Íê£¬¿ÉÒÔ²ÉÓÃ²éÑ¯»òÑÓÊ±·½Ê½(10ms)
    delay_ms(5);
    return TRUE;
}

//×¢Òâ²»ÄÜ¿çÒ³Ð´
//Ð´Èë1´®Êý¾Ý      ´ýÐ´ÈëÊý×éµØÖ·    ´ýÐ´Èë³¤¶È      ´ýÐ´ÈëµØÖ·       Æ÷¼þÀàÐÍ(24c16»òSD2403)
uint8_t I2C_BufferWrite(uint8_t* pBuffer, uint16_t length,     uint16_t WriteAddress, uint8_t DeviceAddress)
{
    if(!I2C_Start())
      return FALSE;
    I2C_SendByte(((WriteAddress & 0x0700) >>7) | DeviceAddress & 0xFFFE);//ÉèÖÃ¸ßÆðÊ¼µØÖ·+Æ÷¼þµØÖ·
    if(!I2C_WaitAck())
    {
      I2C_Stop();
      return FALSE;
    }

    I2C_SendByte((uint8_t)(WriteAddress & 0x00FF));   //ÉèÖÃµÍÆðÊ¼µØÖ·
	  I2C_WaitAck();

		while(length--)
		{
		  I2C_SendByte(* pBuffer);
		  I2C_WaitAck();
        pBuffer++;
		}

	  I2C_Stop();
	  //×¢Òâ£ºÒòÎªÕâÀïÒªµÈ´ýEEPROMÐ´Íê£¬¿ÉÒÔ²ÉÓÃ²éÑ¯»òÑÓÊ±·½Ê½(10ms)
	  delay_ms(5);
	  return TRUE;
}


//¿çÒ³Ð´Èë1´®Êý¾Ý  ´ýÐ´ÈëÊý×éµØÖ·    ´ýÐ´Èë³¤¶È      ´ýÐ´ÈëµØÖ·       Æ÷¼þÀàÐÍ(24c16»òSD2403)
uint8_t I2C_PageWrite(  uint8_t* pBuffer, uint16_t length,     uint16_t WriteAddress, uint8_t DeviceAddress)
{
    uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;
    Addr  = WriteAddress % I2C_PageSize;      //Ð´ÈëµØÖ·ÊÇ¿ªÊ¼Ò³µÄµÚ¼¸Î»
    count = I2C_PageSize - Addr;					    //ÔÚ¿ªÊ¼Ò³ÒªÐ´ÈëµÄ¸öÊý
    NumOfPage   =  length / I2C_PageSize;     //ÒªÐ´ÈëµÄÒ³Êý
    NumOfSingle =  length % I2C_PageSize;     //²»×ãÒ»Ò³µÄ¸öÊý

    if(Addr == 0)         //Ð´ÈëµØÖ·ÊÇÒ³µÄ¿ªÊ¼
    {
      if(NumOfPage == 0)  //Êý¾ÝÐ¡ÓÚÒ»Ò³
      {
        I2C_BufferWrite(pBuffer,NumOfSingle,WriteAddress,DeviceAddress);   //Ð´ÉÙÓÚÒ»Ò³µÄÊý¾Ý
      }
      else		            //Êý¾Ý´óÓÚµÈÓÚÒ»Ò³
      {
        while(NumOfPage)//ÒªÐ´ÈëµÄÒ³Êý
        {
          I2C_BufferWrite(pBuffer,I2C_PageSize,WriteAddress,DeviceAddress);//Ð´Ò»Ò³µÄÊý¾Ý
          WriteAddress +=  I2C_PageSize;
          pBuffer      +=  I2C_PageSize;
					NumOfPage--;
					delay_ms(5);
         }
        if(NumOfSingle!=0)//Ê£ÓàÊý¾ÝÐ¡ÓÚÒ»Ò³
        {
          I2C_BufferWrite(pBuffer,NumOfSingle,WriteAddress,DeviceAddress); //Ð´ÉÙÓÚÒ»Ò³µÄÊý¾Ý
					delay_ms(5);
        }
       }
    }

    else                  //Ð´ÈëµØÖ·²»ÊÇÒ³µÄ¿ªÊ¼
    {
      if(NumOfPage== 0)   //Êý¾ÝÐ¡ÓÚÒ»Ò³
      {
        I2C_BufferWrite(pBuffer,NumOfSingle,WriteAddress,DeviceAddress);   //Ð´ÉÙÓÚÒ»Ò³µÄÊý¾Ý
      }
      else                //Êý¾Ý´óÓÚµÈÓÚÒ»Ò³
      {
        length       -= count;
        NumOfPage     = length / I2C_PageSize;  //ÖØÐÂ¼ÆËãÒªÐ´ÈëµÄÒ³Êý
        NumOfSingle   = length % I2C_PageSize;  //ÖØÐÂ¼ÆËã²»×ãÒ»Ò³µÄ¸öÊý

        if(count != 0)
        {
				  I2C_BufferWrite(pBuffer,count,WriteAddress,DeviceAddress);      //½«¿ªÊ¼µÄ¿Õ¼äÐ´ÂúÒ»Ò³
          WriteAddress += count;
          pBuffer      += count;
         }

        while(NumOfPage--)  //ÒªÐ´ÈëµÄÒ³Êý
        {
          I2C_BufferWrite(pBuffer,I2C_PageSize,WriteAddress,DeviceAddress);//Ð´Ò»Ò³µÄÊý¾Ý
          WriteAddress +=  I2C_PageSize;
          pBuffer      +=  I2C_PageSize;
        }
        if(NumOfSingle != 0)//Ê£ÓàÊý¾ÝÐ¡ÓÚÒ»Ò³
        {
          I2C_BufferWrite(pBuffer,NumOfSingle,WriteAddress,DeviceAddress); //Ð´ÉÙÓÚÒ»Ò³µÄÊý¾Ý
        }
      }
    }
		return TRUE;
}

//¶Á³ö1´®Êý¾Ý         ´æ·Å¶Á³öÊý¾Ý  ´ý¶Á³ö³¤¶È      ´ý¶Á³öµØÖ·       Æ÷¼þÀàÐÍ(24c16»òSD2403)
uint8_t I2C_ReadByte(uint8_t* pBuffer,   uint16_t length,     uint16_t ReadAddress,  uint8_t DeviceAddress)
{
    if(!I2C_Start())
      return FALSE;
    I2C_SendByte(((ReadAddress & 0x0700) >>7) | DeviceAddress & 0xFFFE);//ÉèÖÃ¸ßÆðÊ¼µØÖ·+Æ÷¼þµØÖ·
    if(!I2C_WaitAck())
    {
      I2C_Stop();
      return FALSE;
    }
    I2C_SendByte((uint8_t)(ReadAddress & 0x00FF));   //ÉèÖÃµÍÆðÊ¼µØÖ·
    I2C_WaitAck();

    I2C_Start();
    I2C_SendByte(((ReadAddress & 0x0700) >>7) | DeviceAddress | 0x0001);
    I2C_WaitAck();
    while(length)
    {
      *pBuffer = I2C_ReceiveByte();
      if(length == 1)
        I2C_NoAck();
      else
        I2C_Ack();
      pBuffer++;
      length--;
    }
    I2C_Stop();
    delay_ms(5);
    return TRUE;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//延时函数
void AD7416_delay()
{
unsigned int i=60;
while(i--);
}
/*--------------------------------------------------------------------------------
调用方式：void AD7416_I2CStart(void) ﹫2001/07/0 4
函数说明：私有函数，I2C专用
---------------------------------------------------------------------------------*/
void AD7416_I2CStart(void)
{
//EA=0;
SDA_H; SCL_H; AD7416_delay();//INI
SDA_L; AD7416_delay();//START
SCL_L; AD7416_delay();
}
/*--------------------------------------------------------------------------------
调用方式：void AD7416_I2CStop(void) ﹫2001/07/0 4
函数说明：私有函数，I2C专用
---------------------------------------------------------------------------------*/
void AD7416_I2CStop(void)
{
SCL_L; SDA_L; AD7416_delay();//INI
SCL_H; AD7416_delay();//STOP
//EA=1;
}
uint8_t AD7416_WaitAck(void)
{
unsigned char errtime=255;//因故障接收方无ACK，超时值为255。
SDA_H;AD7416_delay();
SCL_H;AD7416_delay();
AD7416_SystemError=0x10;
while(Chip(11))
{ errtime--;
if(!errtime)
{ AD7416_I2CStop();
AD7416_SystemError=0x11;
return FALSE;
}
}
SCL_L; AD7416_delay();
return TRUE;
}
void AD7416_SendNotAck(void)
{
SDA_H; AD7416_delay();
SCL_H; AD7416_delay();
SCL_L; AD7416_delay();
}
void AD7416_I2CSendByte(unsigned char ch)
{
unsigned char i=8;
while(i--)
{
SCL_L;
_nop_();
AD7416_delay();
//SDA_PIN=(bit)(ch&0x80); ch<<=1; AD7416_delay();

if(ch&0x80)
       SDA_H;
     else
       SDA_L;
     ch<<=1;
     I2C_delay();
SCL_H; AD7416_delay();
}
SCL_L; AD7416_delay();
}
unsigned char AD7416_I2CReceiveByte(void)
{
unsigned char i=8;
unsigned char dat=0;
SDA_H;
while(i--)
{
dat<<=1;
SCL_L;AD7416_delay();
SCL_H;AD7416_delay();
dat|=SDA_PIN;
}
SCL_L; AD7416_delay();
return(dat);
}
/*--------------------------------------------------------------------------
ACK BY MASTER 有CPU给传感器一个低，所以这个ACK是来自CPU的。
---------------------------------------------------------------------------*/
void AD7416_bitout()
{
SDA_L; AD7416_delay();
SCL_L; AD7416_delay();
SDA_L; AD7416_delay();
SCL_H; AD7416_delay();
SCL_L; AD7416_delay();
}
unsigned int Read7416(unsigned char address)
{
unsigned char h,l,temp,c;
unsigned int wendu;

AD7416_I2CStart();
AD7416_I2CSendByte(address); //写
AD7416_WaitAck();
AD7416_I2CSendByte(0x00); //指向温度寄存器
AD7416_SendNotAck();
AD7416_I2CStop();

AD7416_I2CStart();
AD7416_I2CSendByte(address+1); //读
AD7416_WaitAck();
h=AD7416_I2CReceiveByte(); //读高8位
AD7416_bitout(); //CUP送低
l=AD7416_I2CReceiveByte(); //读低8位
AD7416_SendNotAck();
AD7416_I2CStop();

c=2; //循环两次
wendu=h;temp=l;
//将高8位和低8位的前2位连接
while(c--)
{
if(temp&0x80)
{
wendu<<=1;
wendu|=0x0001;
}
else
{
wendu<<=1;
}
}
//判断温度正负
if(h&0x80) //负
{
wendu=wendu-0x01;
wendu=~wendu; //变回原码
wendu=wendu&0x03FF;
wendu=wendu*0.25;
Temperature=wendu;
ZorF=0;
}
else //正
{
wendu=wendu*0.25;
Temperature=wendu;
ZorF=1;
}
return Temperature;
}
/////////////////////////////////////////////////////自己加的/////////////////////////////////////////////////////////

unsigned int Read741611(unsigned char address)
{
unsigned char h,l,temp,c;
unsigned int wendu;

if(!I2C_Start())return FALSE;
	    I2C_SendByte(0x90); //128,   // sensor I2C address + write bit
	    if(!I2C_WaitAck())
			{I2C_Stop(); return FALSE;}
	    I2C_SendByte(0x00);     // 0xF3TRIG_T_MEASUREMENT_POLL
	    I2C_WaitAck();
			delay_us(20);
		  I2C_Stop();
			do
			{
			DELAY(100);
			I2C_Start();
	        I2C_SendByte(0x91);
			}
			while(!I2C_WaitAck());
	h=I2C_ReceiveByte();
		//	printf("%c\r\n",Tdata[0]);
			I2C_Ack();
	l=I2C_ReceiveByte();
		//	printf("%c\r\n",Tdata[1]);

			I2C_NoAck();
			I2C_Stop();

c=2; //循环两次
wendu=h;temp=l;
//将高8位和低8位的前2位连接
while(c--)
{
if(temp&0x80)
{
wendu<<=1;
wendu|=0x0001;
}
else
{
wendu<<=1;
}
}
//判断温度正负
if(h&0x80) //负
{
wendu=wendu-0x01;
wendu=~wendu; //变回原码
wendu=wendu&0x03FF;
wendu=wendu*0.25;
Temperature=wendu;
ZorF=0;
}
else //正
{
wendu=wendu*0.25;
Temperature=wendu;
ZorF=1;
}
return Temperature;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//设定7416的OTI和HYST
/*----------------------------------------------------------------------------
OTI为上限 HYST为下限
7416做为恒温器使用 OTI必须低有效。当温度高于OTI值时由OTI脚发出低，直到温度低于
HYST值OTI脚才发出高。
-----------------------------------------------------------------------------*/
void Setup7416OTI(unsigned char OTI,unsigned char HYST,unsigned char address)
{

unsigned char a,b;

a=OTI; //温度转换
a=a*4;
a>>=2;

b=HYST; //温度转换
b=b*4;
b>>=2;

AD7416_I2CStart();
AD7416_I2CSendByte(address); //写
AD7416_WaitAck();
AD7416_I2CSendByte(0x01); //指向状态寄存器
AD7416_WaitAck();
AD7416_I2CSendByte(0x18);
AD7416_SendNotAck();
AD7416_I2CStop();

AD7416_I2CStart();
AD7416_I2CSendByte(address); //写
AD7416_WaitAck();
AD7416_I2CSendByte(0x03); //指向OTI存器
AD7416_WaitAck();
AD7416_I2CSendByte(a); //送温度高8位
AD7416_WaitAck();
AD7416_I2CSendByte(0x00); //送温度低8位
AD7416_SendNotAck();
AD7416_I2CStop();


AD7416_I2CStart();
AD7416_I2CSendByte(address); //写
AD7416_WaitAck();
AD7416_I2CSendByte(0x02); //指向HYST寄存器
AD7416_WaitAck();
AD7416_I2CSendByte(b); //送温度高8位
AD7416_WaitAck();
AD7416_I2CSendByte(0x00); //送温度低8位
AD7416_SendNotAck();
AD7416_I2CStop();
}

